Skip to content

ci(tests): shard the server suite across a 4-runner matrix - #717

Merged
marceld23 merged 2 commits into
mainfrom
ci/shard-tests
Aug 4, 2026
Merged

ci(tests): shard the server suite across a 4-runner matrix#717
marceld23 merged 2 commits into
mainfrom
ci/shard-tests

Conversation

@marceld23

Copy link
Copy Markdown
Owner

Closes #716

What

The PR gate spent 11:25 of its 12:40 running the server suite on a single 4-vCPU runner — and the suite already scales ~perfectly in-process (2550 s summed ÷ maxParallelThreads: 4 ≈ the observed wall; the pin is deliberate, #536). So this fans the suite out over a 4-job matrix instead:

  • scripts/partition-tests.py — deterministic class→shard packing (greedy by weight, heaviest first) + per-shard --filter emission. Tokens are dot-anchored (FullyQualifiedName~.Class.) because ~ is substring matching.
  • scripts/test-shard-weights.json — real per-class trx seconds from run 30862522491; new classes get a 10 s default until the file is refreshed.
  • Completeness guard (shard 1): every test in dotnet test --list-tests output must match exactly one shard's filter — a nested class or naming collision fails the build loudly instead of silently never running. The parser doesn't key off the localized "Tests are available" header.
  • Tests passed fan-in job — the single stable-name required check standing in for the matrix; passes iff all shards succeeded or were skipped as docs-only (with the changes helper itself green).
  • Shard 1 also carries the 11 s Client.Tests suite; shards 2–4 don't restore/build it at all. Duration guardrail + trx artifacts are per-shard.

Verification

  • All 4 shard filters run locally (Release, fast tier): 461+376+237+324 = 1398 — exactly the fast-tier total, all green.
  • verify maps all 1450 listed tests (incl. Slow) to exactly one shard.
  • Weighted balance: ~652 s per shard.

Expected

PR gate ~12:40 → ~4:30; push-to-main full runs shrink proportionally.

⚠ Merge choreography

Branch protection must swap required check Build + test (.NET, headless)Tests passed at merge time (doing it before hurts nothing either — this PR's run produces both Tests passed and the shard checks). release.yml is untouched.

🤖 Generated with Claude Code

marceld23 and others added 2 commits August 4, 2026 02:48
The PR gate spent 11:25 of its 12:40 in one Test step: the server suite
(1398 fast-tier tests, ~2550 s summed) already scales ~perfectly with the
4 cores a single runner has (maxParallelThreads is pinned to 4 — #536),
so the remaining parallelization is more runners, not more threads.

scripts/partition-tests.py deterministically packs test CLASSES onto 4
shards (greedy by weight; scripts/test-shard-weights.json holds real trx
seconds, new classes get a default) and emits per-shard dot-anchored
FullyQualifiedName filters. Classes are parsed from source declarations,
not file names (one file declares two classes today). Shard 1 additionally
runs the 11 s Client.Tests suite and cross-checks `dotnet test
--list-tests` output: every discovered test must match exactly one
shard's filter, so a partition miss fails the build instead of silently
never running a class. The duration guardrail runs per shard; trx
artifacts are per-shard.

Branch protection swaps its required check to the new `Tests passed`
fan-in (matrix names carry the shard index and can't be required; the
fan-in passes iff all shards succeeded or were skipped as docs-only with
the `changes` helper green).

Verified locally: all 4 shard filters together execute 461+376+237+324 =
exactly the 1398 fast-tier tests, all green; partition verify covers all
1450 listed tests (incl. Slow).

Closes #716

Co-Authored-By: Claude Fable 5 <[email protected]>
Four required checks, not five — CodeQL runs on PRs but was never in the
required set (verified via the branch-protection API while swapping in
`Tests passed` for #716).

Co-Authored-By: Claude Fable 5 <[email protected]>
@marceld23
marceld23 merged commit 6c413e2 into main Aug 4, 2026
16 checks passed
@marceld23
marceld23 deleted the ci/shard-tests branch August 4, 2026 00:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI: shard the server test suite across 4 runners — PR gate spends 11 of its 12.7 minutes in one test job

1 participant